import cv2
import numpy as np
from PIL import Image, ImageTk
import imutils
from LipFeaturaExtract.landmarks import FaceLandmarks,normalization
from LSTMModel.prediction import Model


"""
预测模型类，用于视频流帧的判断、保存和预测
"""
class LipPredictionMoel(Model):
    def __init__(self,weight_path,label_path,
                 predict_frame_number,threshold,
                 scaling_factor,graph):
        super(LipPredictionMoel,self).__init__(weight_path,label_path,graph)
        self._faceLandmarks=FaceLandmarks(scaling_factor=scaling_factor,
                                          extract_face=False)
        self._predict_frame_number=predict_frame_number
        self._threshold=threshold
        self._video_seq_data=[]
        self._continuity_lack_frame=0

    def judgeLipFeature(self,frame):
        """
        用于判读是否存在唇部特征
        :param frame: 视频帧
        :return:
        """
        lip_features = self._faceLandmarks.extractLandmarks(frame)
        if len(lip_features) == 1:
            w = frame.shape[1]
            h = frame.shape[0]
            lip_feature = normalization(lip_features, w, h)[0]
            return lip_feature
        else:
            return []

    def predictLipFeature(self,frame):
        """
        用于视频帧的保存
        :param frame:图片帧
        :return:
        """
        lip_feature=self.judgeLipFeature(frame)
        if lip_feature:
            self._video_seq_data.append(lip_feature)
            video_data_len=len(self._video_seq_data)
            self._continuity_lack_frame=0   # 连续缺少置零
            if video_data_len>=self._predict_frame_number and video_data_len<=self._predict_frame_number+20\
                    and video_data_len%5==0:
                outcome=self.predict([self._video_seq_data])[0]
                if outcome[1]>self._threshold:
                    self._video_seq_data=[]
                    return outcome
                else:
                    self._video_seq_data=deleteListValue(self._video_seq_data,
                                                         0,5)
                    return None
            else:
                if video_data_len>=self._predict_frame_number+20:
                    self._video_seq_data=deleteListValue(self._video_seq_data,
                                                         0,5)
                return None
        else:
            self._continuity_lack_frame+=1
            if self._continuity_lack_frame>=5:  # 连续缺少超过6帧，清空缓存
                self._video_seq_data=[]
                self._continuity_lack_frame=0

            return None

    def run(self,gui,method=0):
        # 加载摄像头
        cap = cv2.VideoCapture(method)
        ret = True
        gui.is_run = True
        while ret and gui.is_run:
            ret, frame = cap.read()  # 读取一帧图片
            if ret:
                outcome = self.predictLipFeature(frame)
                if outcome is not None:
                    if gui.flag==4:
                        gui.outputAllPredictWord(outcome[0],outcome[1],1)
                    else:
                        gui.outputPredictWord(str.lower(outcome[0]))
                frame = imutils.resize(frame, width=500)  # 修改尺寸
                frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)  # 转换颜色通道
                frame = Image.fromarray(frame)  # 转换为image类型
                frame = ImageTk.PhotoImage(frame)
                gui.panel.configure(image=frame)
                gui.panel.image = frame

        frame = np.full(shape=(375, 500, 3), fill_value=255,
                        dtype=np.uint8)
        frame = Image.fromarray(frame)  # 转换为image类型
        frame = ImageTk.PhotoImage(frame)
        gui.panel.configure(image=frame)
        gui.panel.image = frame

        gui.outputPredictWord("")



def deleteListValue(data_list,start_index,delete_number):
    """
    删除从索引位置上开始了number个元素
    :param data_list: 列表
    :param start_index: 索引位置
    :param delete_number: 删除个数
    :return:
    """
    for _ in range(delete_number):
        data_list.pop(start_index)
    return data_list
